
open Asp

(* Le niveau que on est actuellement entraindre d'affiche *)
let niveau = ref 0

(* On passe a un sous niveau *)
let up () =
	niveau := !niveau + 1;
	()

(* On remonte d'un niveau *)	
let down () =
	niveau := !niveau - 1;
	()

(* On affiche la tabulation d'apres le nivau actuel *)
let rec tab n =
		if n > 0 then (print_char '\t'; tab (n-1)) else ()

(* Fonction qui affiche une ligne avec la tablulation *)
let echo s =
	
	tab !niveau;
	print_endline s;
	()

(* Retourn le string du typev de l'arbre *)
let rec dessiner_typev typev =
	match typev with
	| Void -> "void"
	| Entier -> "entier"
	| Caractere -> "caractere"
	| Pointeur(t) -> "pointeur de " ^ (dessiner_typev t)
	| Type_struct(strin) -> "structure " ^ strin
	| Type_union(strin) -> "union " ^ strin

(* Dessine une variable, avec son nom et son type *)
let dessiner_var var typev =
	let n = ref "" in
	let rec r var =
		match var with
		| Identificateur(s) -> n := s; dessiner_typev typev
		| Pointeur_var(v) -> "pointeur sur (" ^ (r v) ^ ")"
		| Tableau (v,i) -> "tableau de (" ^ (r v) ^ ") de taille " ^ (string_of_int i)
	in
	up ();
	echo (!n ^ " : " ^ (r var));
	down ()
	
(* Dessine la liste des arguments que prend une fonction en parametre *)
let dessiner_args args =
	let rec r args =
		match args with
		| [] -> ()
		| a::s -> (match a with
			| Argument (var,typev) -> dessiner_var var typev
		 ); r s
	in
	up ();
	echo "arguments :";
	r args;
	down ()

(* Dessine e type operator *)
let dessiner_op o = 
	match o with
		|Egal -> print_string "=="
		|Different -> print_string "!="
		|Inf -> print_char '<'
		|Inf_eq -> print_string "<="
		|Sup -> print_char '>'
		|Sup_eq -> print_string ">="
		|Somme -> print_char '+'
		|Soustraction -> print_char '-'
		|Multiplication -> print_char '*'
		|Division -> print_char '/'
		|Modulo -> print_char '%'
		|Et -> print_string "&&"
		|Ou -> print_string "||"

(* Dessine le tab passer en parametre aux sizeof *)
let rec dessiner_tabInt il = 
	match il with
		|i::l -> (print_string"["); (print_int i); (print_string"]"); dessiner_tabInt l
		| [] -> ()

(* Dessine une expression *)
let rec dessiner_exp ex =
	print_char '(';
	let i = match ex with
			|NOP -> print_string "NOP"
			|Cst(i) -> print_string (string_of_int i)
			|Car(c) -> print_string ("\'" ^ (Char.escaped c) ^ "\'")
			|Chaine(s) -> print_string ("\""^s^"\"")
			|Ident(s) -> print_string s
			|Assignation(e1,e2) -> (dessiner_exp e1); print_string "="; (dessiner_exp e2)
			|Binop(o,e1,e2) -> (dessiner_exp e1); (dessiner_op o); (dessiner_exp e2)
			|Appel_fun(s, el) -> print_string s; print_char '('; dessiner_exp_list el; print_char ')'
			|Acces_tableau(e1, e2) -> (dessiner_exp e1); print_char '['; (dessiner_exp e2); print_char ']'
			|Acces_pointeur(e1) ->  print_char '*'; (dessiner_exp e1)
			|Contenu_pointeur(e1,s) -> (dessiner_exp e1); print_string s
			|Contenu_variable(e1, s)-> (dessiner_exp e1); print_string "->"; print_string s
			|Reference(e1)-> print_char '&'; (dessiner_exp e1)
			|Non(e1)->print_char '!'; (dessiner_exp e1)
			|Plus_Plus_Expr(e1)->print_string "++"; (dessiner_exp e1)
			|Moins_Moins_Expr(e1)->print_string "--"; (dessiner_exp e1)
			|Expr_Plus_Plus(e1)-> (dessiner_exp e1); print_string "++"
			|Expr_Moins_Moins(e1)-> (dessiner_exp e1); print_string "--"
			|Sizeof(c) ->
				let (t,il) = match c with
							| Type_complexe(t, il) -> (t, il)
				 in 
				 (print_string "sizeof("); 
				 (print_string (dessiner_typev t)); (dessiner_tabInt il); print_string ")"

	in
	print_char ')'
(* Dessine une liste d'expression pour les parametre passe a une fonction *)
and dessiner_exp_list ex = 
	(* L'affichage ddes autre parametre avec un , *)
	let rec other ex = 
		match ex with
			|e::l -> print_string " , "; dessiner_exp e;  other l
			| [] -> ()
	in 
	(* L'affichage du premier parametre *)
	let first ex = 
		match ex with
			| e::l -> dessiner_exp e; other l; 
			|[] -> ()
	in
	
	first ex

(* Dessine le contenu d'une stucture *)
let dessiner_content content = ()

(* Dessine la liste d'instruction *)
let rec dessiner_instr_list instr_list = 
	match instr_list with
	| [] -> ()
	| a::s -> dessiner_instr a; dessiner_instr_list s
and
	(* Dessine une instruction *)
	dessiner_instr instr = 
	match instr with
	|Expression(e) -> 
				tab !niveau; 
				dessiner_exp e; 
				print_char '\n'
				
	|Bloc (instr_declaration_list, instr_list) -> 
				dessiner_programme instr_declaration_list; 
				dessiner_instr_list instr_list
				
	|If(e1, i1,i2)-> 
				tab !niveau; 
				print_string "if"; 
				dessiner_exp e1; print_char '\n';
				up(); 
				dessiner_instr i1;
				down(); 
				tab !niveau; 
				print_string "else"; 
				print_char '\n'; 
				up(); 
				dessiner_instr i2;
				down();
				print_char '\n';
				print_char '\n'
				
	|While(e1, i1)->
				tab !niveau; 
				print_string "while"; 
				dessiner_exp e1; 
				print_char '\n'; 
				up();  
				dessiner_instr i1;
				down()
				
	|For(e_list1, e1, e_list2, i1) ->
				tab !niveau; 
				print_string "For( "; 
				dessiner_exp_list e_list1;
				print_string " ; ";
				dessiner_exp e1;
				print_string " ; ";
				dessiner_exp_list e_list2;
				print_string " )"; 
				print_char '\n'; 
				up(); 
				dessiner_instr i1;
				down()
	|Retour (e1)->
				tab !niveau; 
				print_string "return"; 
				dessiner_exp e1
and
	(* Dessine une instruction de declaration *)
	dessiner_instr_declaration (racine:Asp.instr_declaration) =
	match racine with
	| Declaration_var_g(var,typev) -> 
				echo "variable globale"; 
				dessiner_var var typev
				
	| Declaration_fun(strin,typev,args,instr) -> 
				echo ("fonction (" ^ (dessiner_typev typev) ^ ") " ^ strin ^ " :"); 
				dessiner_args args; 
				up (); 
				dessiner_instr instr; 
				down ()
				
	| Struct(strin,content) -> 
				echo ("structure "^strin); 
				dessiner_content content
				
	| Union(strin,content) -> 
				echo ("union "^strin); 
				dessiner_content content
and
	(* Dessine le programme. la fonction principale *)
	dessiner_programme (prog:Asp.instr_declaration_list) =
	match prog with
	| [] -> ()
	| a::s -> dessiner_instr_declaration a; dessiner_programme s
 







